﻿@inherits OwningComponentBase<ICovenantService>

@using Microsoft.JSInterop
@using Microsoft.AspNetCore.Components.Forms
@using Covenant.Core
@using Covenant.Models.Grunts
@inject IJSRuntime IJSRuntime

<EditForm Model="ReferenceSourceLibrary" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <div class="form-row">
        <div class="form-group col-md-4">
            <label for="Name">Name</label>
            <input id="Name" name="Name" @bind="ReferenceSourceLibrary.Name" class="form-control">
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.Name" /></div>
        </div>
        <div class="form-group col-md-8">
            <label for="Description">Description</label>
            <input id="Description" name="Description" @bind="ReferenceSourceLibrary.Description" class="form-control">
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.Description" /></div>
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-12">
            <label for="Location">Location</label>
            <input id="Location" name="Location" @bind="ReferenceSourceLibrary.Location" class="form-control">
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.Location" /></div>
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-3">
            <label for="Language">Language</label><br />
            <select id="Language" name="Language" @bind="ReferenceSourceLibrary.Language" class="selectpicker show-menu-arrow" data-dropup-auto="false" data-width="auto">
                @foreach (var n in Enum.GetNames(typeof(ImplantLanguage)))
                {
                    if (Enum.TryParse<ImplantLanguage>(n, out ImplantLanguage language) && this.ReferenceSourceLibrary.Language == language)
                    {
                        <option selected value="@(((Enum)typeof(ImplantLanguage).GetField(n).GetValue(null)).ToString("d"))">@n</option>
                    }
                    else
                    {
                        <option value="@(((Enum)typeof(ImplantLanguage).GetField(n).GetValue(null)).ToString("d"))">@n</option>
                    }
                }
            </select>
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.Language" /></div>
        </div>
        @if (this.ReferenceSourceLibrary.Language == ImplantLanguage.CSharp)
        {
            <div class="form-group col-md-3">
                <label for="CompatibleDotNetVersions">CompatibleDotNetVersions</label><br />
                <select id="CompatibleDotNetVersions" name="CompatibleDotNetVersions" class="selectpicker show-menu-arrow" multiple data-dropup-auto="false" data-width="auto" data-live-search="true" data-selected-text-format="count > 2">
                    @foreach (var n in Enum.GetNames(typeof(Common.DotNetVersion)))
                    {
                        if (Enum.TryParse<Common.DotNetVersion>(n, out Common.DotNetVersion version) && this.ReferenceSourceLibrary.CompatibleDotNetVersions.Contains(version))
                        {
                            <option selected value="@(((Enum)typeof(Common.DotNetVersion).GetField(n).GetValue(null)).ToString("d"))">@n</option>
                        }
                        else
                        {
                            <option value="@(((Enum)typeof(Common.DotNetVersion).GetField(n).GetValue(null)).ToString("d"))">@n</option>
                        }
                    }
                </select>
                <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.CompatibleDotNetVersions" /></div>
            </div>
        }
    </div>
    <div class="form-row">
        <div class="form-group col-md-5">
            <label for="EmbeddedResources">EmbeddedResources</label><br />
            <select id="EmbeddedResources" name="EmbeddedResources" @onchange="OnChangeEmbeddedResources" class="selectpicker show-menu-arrow" multiple data-dropup-auto="false" data-width="auto" data-live-search="true" data-selected-text-format="count > 2">
                @foreach (EmbeddedResource resource in GetEmbeddedResources())
                {
                    if (this.ReferenceSourceLibrary.EmbeddedResources.Contains(resource))
                    {
                        <option @key="resource" selected value="@resource.Id">@resource.Name</option>
                    }
                    else
                    {
                        <option @key="resource" value="@resource.Id">@resource.Name</option>
                    }
                }
            </select>
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.EmbeddedResources" /></div>
        </div>
        <div class="form-group col-md-6">
            <label for="ReferenceAssemblies">ReferenceAssemblies</label><br />
            <select id="ReferenceAssemblies" name="ReferenceAssemblies" @onchange="OnChangeReferenceAssemblies" class="selectpicker show-menu-arrow" multiple data-dropup-auto="false" data-width="auto" data-live-search="true" data-selected-text-format="count > 2">
                @foreach (ReferenceAssembly assembly in GetReferenceAssemblies())
                {
                    if (this.ReferenceSourceLibrary.ReferenceAssemblies.Contains(assembly))
                    {
                        <option @key="assembly" selected value="@assembly.Id">@assembly.Name (@assembly.DotNetVersion.ToString())</option>
                    }
                    else
                    {
                        <option @key="assembly" value="@assembly.Id">@assembly.Name (@assembly.DotNetVersion.ToString())</option>
                    }
                }
            </select>
            <div class="text-danger"><ValidationMessage For="() => ReferenceSourceLibrary.ReferenceAssemblies" /></div>
        </div>
    </div>

    <button type="submit" class="btn btn-primary">
        <span class="fe fe-@SubmitIcon"></span>@SubmitLabel
    </button>
</EditForm>

@code {
    private ReferenceSourceLibrary _ReferenceSourceLibrary;
    [Parameter]
    public ReferenceSourceLibrary ReferenceSourceLibrary
    {
        get
        {
            return _ReferenceSourceLibrary;
        }
        set
        {
            if (value != null && value.Id > 0)
            {
                _ReferenceSourceLibrary = Service.GetReferenceSourceLibrary(value.Id).WaitResult();
            }
            else
            {
                _ReferenceSourceLibrary = value;
            }
        }
    }

    [Parameter]
    public string SubmitIcon { get; set; }

    [Parameter]
    public string SubmitLabel { get; set; }

    [Parameter]
    public EventCallback<ReferenceSourceLibrary> OnSubmit { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await IJSRuntime.InvokeAsync<string>("InitializeSelectPicker", "#Language.selectpicker", ((int)Enum.Parse(typeof(ImplantLanguage), this.ReferenceSourceLibrary.Language.ToString())).ToString());
        await IJSRuntime.InvokeAsync<string>("InitializeSelectPicker", "#ReferenceAssemblies.selectpicker");
        await IJSRuntime.InvokeAsync<string>("InitializeSelectPicker", "#EmbeddedResources.selectpicker");
        if (this.ReferenceSourceLibrary.Language == ImplantLanguage.CSharp)
        {
            await IJSRuntime.InvokeAsync<string>("InitializeSelectPicker", "#CompatibleDotNetVersions.selectpicker");
        }
    }

    private IEnumerable<ReferenceAssembly> GetReferenceAssemblies()
    {
        Task<IEnumerable<ReferenceAssembly>> t = Service.GetReferenceAssemblies();
        t.Wait();
        return t.Result;
    }

    private IEnumerable<EmbeddedResource> GetEmbeddedResources()
    {
        return Service.GetEmbeddedResources().WaitResult();
    }

    private async Task OnChangeReferenceAssemblies()
    {
        string[] ras = await IJSRuntime.InvokeAsync<string[]>("GetValue", new object[] { "#ReferenceAssemblies" });
        IEnumerable<int> ids = ras.Where(id => int.TryParse(id, out _)).Select(sid => int.Parse(sid));
        IEnumerable<int> adds = ids.Where(id => !this.ReferenceSourceLibrary.ReferenceAssemblies.Select(RA => RA.Id).Contains(id));
        IEnumerable<int> removes = this.ReferenceSourceLibrary.ReferenceAssemblies.Select(RA => RA.Id).Where(id => !ids.Contains(id));
        foreach (int id in adds)
        {
            this.ReferenceSourceLibrary.Add(await Service.GetReferenceAssembly(id));
        }
        foreach (int id in removes)
        {
            this.ReferenceSourceLibrary.Remove(this.ReferenceSourceLibrary.ReferenceAssemblies.Find(RA => RA.Id == id));
        }
    }

    private async Task OnChangeEmbeddedResources()
    {
        string[] ers = await IJSRuntime.InvokeAsync<string[]>("GetValue", new object[] { "#EmbeddedResources" });
        IEnumerable<int> ids = ers.Where(id => int.TryParse(id, out _)).Select(sid => int.Parse(sid));
        IEnumerable<int> adds = ids.Where(id => !this.ReferenceSourceLibrary.EmbeddedResources.Select(ER => ER.Id).Contains(id));
        IEnumerable<int> removes = this.ReferenceSourceLibrary.EmbeddedResources.Select(ER => ER.Id).Where(id => !ids.Contains(id));
        foreach (int id in adds)
        {
            this.ReferenceSourceLibrary.Add(await Service.GetEmbeddedResource(id));
        }
        foreach (int id in removes)
        {
            this.ReferenceSourceLibrary.Remove(this.ReferenceSourceLibrary.EmbeddedResources.Find(ER => ER.Id == id));
        }
    }

    private async Task<List<Common.DotNetVersion>> GetCompatibleDotNetVersions()
    {
        string[] ids = await IJSRuntime.InvokeAsync<string[]>("GetValue", new object[] { "#CompatibleDotNetVersions" });
        return ids.Where(id => Enum.TryParse<Common.DotNetVersion>(id, out _)).Select(id => Enum.Parse<Common.DotNetVersion>(id)).ToList();
    }

    private async Task Submit()
    {
        this.ReferenceSourceLibrary.CompatibleDotNetVersions = await GetCompatibleDotNetVersions();
        await this.OnSubmit.InvokeAsync(this.ReferenceSourceLibrary);
    }
}
